/*
 *	Copyright 2011 andro-inject developers 
 *	Licensed under the Apache License, Version 2.0 (the "License"); 
 *	you may not use this file except in compliance with the License. 
 *	You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 * 
 *	Unless required by applicable law or agreed to in writing, software 
 *	distributed under the License is distributed on an "AS IS" BASIS,
 *	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *	See the License for the specific language governing permissions and
 *	limitations under the License. 
 * 
*/

package com.androinject.core;


/**
 *	ComponentFactory is the standard interface to access andro-inject components.
 *  Implementations typically manage a set of component definitions that are used to create components
 *  and inject dependencies into them. A xml component definition file is the standard way to give
 *  a set of component definitions to a ComponentFactory (other ways are possible too). <br /><br />
 *  ComponentFactory differences between two types of components: <br /><br />
 *  <b>Standard components:</b> Standard components are created by ComponentFactory. Either on startup or when 
 *  the component is requested the first time (lazy initialization). <br /><br />
 *  <b>Managed components:</b> These components aren't created by ComponentFactory. Managed component definitions
 *  can be used for objects that have their own instance management (e.g. singletons). Even if ComponentFactory 
 *  does not create managed components, ComponentFactory can still be used to inject dependencies
 *  into managed components.
 *    
 */
public interface ComponentFactory {
	
	/**
	 * Returns an instance of the component with the passed id.
	 * If the component with the passed id has already been created this component will be returned.
	 * ComponentFactory does not create a second component instance. If no component instance is available
	 * ComponentFactory looks for a component definition with the passed <i>id</i>. A new component instance
	 * will be created based on the component definition. Dependencies are injected and the initialization method is 
	 * called (if defined). If no component definition with <i>id</i> is found, 
	 * ComponentDefinitionNotFoundException will be thrown.
	 * @param id the id of the component to retrieve
	 * @return an instance of the component
	 */
	public Object getComponent(String id);
	
	
	/**
	 * Returns an instance of the component with the passed id.
	 * Works like getComponent(String id) but does an additional typecast to <i>requiredClass</i>. This is
	 * the typesafe version of getComponent(String id). If the cast fails ClassCastException will be thrown.
	 * @param id the id of the component to retrieve
	 * @param requiredClass Class of the component
	 * @return an instance of the component
	 */
	public <T> T getComponent(String id, Class<T> requiredClass);
	
	
	/**
	 * Initializes a managed component.
	 * ComponentFactory looks for a managed component definition with the passed <i>id</i> and initializes 
	 * <i>componentToInject</i> based on this definition. Dependencies are injected and the initialization 
	 * method is called (if defined). If no managed component definition with <i>id</i> is found, 
	 * ComponentDefinitionNotFoundException will be thrown.
	 * @param componentToInitialize the component that should be initialized
	 * @param id the id of the managed component
	 */
	public void initializeManagedComponent(Object componentToInitialize, String id);
	
	
	/**
	 * Initializes a managed component.
	 * Works exactly like initializeManagedComponent(Object componentToInitialize, String id). The <i>id</i> 
	 * parameter will be generated based of the class name of <i>componentToInitialize</i>. E.g. the class 
	 * name <i>UserProfileController</i> will be converted to the id <i>userProfileController</i>.
	 * @param componentToInitialize the component that should be initialized
	 */
	public void initializeManagedComponent(Object componentToInitialize);
	
	
	/**
	 * Returns the type of the component with the passed id.
	 * If no component with the passed <i>id</id> exists <i>null</i> will be returned.
	 * @param id the id of the component
	 * @return the type of the component
	 */
	public Class<?> getType(String id);

}
